const log4js = require("log4js");
const logger = log4js.getLogger();

const mongoose = require("mongoose")

const ResponseMessage = require("../response/message");

const {
     findOrderByOrderNo,
     updateOrderStatus
} = require("../persistent_api/orderApi")

const {
    findStudentById,
    updateStudentMoney
} = require("../persistent_api/studentApi")

const {
     findTeacherById,
     updateTeacherMoney
} = require("../persistent_api/teacherApi")


const paySocket = require("../socket/paySocket")

const config = require("../config")

exports.pay = async (req,res) => {
     /**
      * 1. 得到订单号查询订单信息
      * 2. 判断订单是否过期 如果过期修改状态为已过期
      * 3. 通过查询到的订单信息里面的付款方用户ID查询用户信息显示余额到界面
      * 4. 用户点击支付按钮 进行支付 请求处理支付接口 将支付接口的 return_url 和 notify_url 一并携带过去 修改参与交易账户的余额 使用事务控制数据一致性
      * 5. 支付成功/失败 手机端跳转同步通知页面  支付服务器并通知异步接口地址支付结果 成功与失败 都是用 websocket 通知PC前端 / 
      * 6. 如果是移动端则在移动端同步通知页面告知用户是否支付成功
      */
      let orderNo;
      try{
          const {orderNo,return_url, notify_url} = req.query;
          const order = (await findOrderByOrderNo(orderNo))[0];
          if(order){
               if(Date.now() > order.tradeOutDate || order.tradePayStatus === 1){
                    if(order.tradePayStatus !== 1) await updateOrderStatus(orderNo,1);
                    paySocket.notify("pay",1)
                    res.render("payOverTime"); 
               }else{
                    if(order.tradePayStatus === 2){
                         res.render("pay",{
                              isOk:true,
                              return_url
                         });
                    }else{
                         let balance = 0 , role = null;
                         const teacher = await findTeacherById(order.fromId);
                         const student = await findStudentById(order.fromId);
                         let noDollar = false;
                         if(teacher && teacher.length > 0){
                              balance = teacher[0]?.dollar;
                              role = "teacher";
                              if(balance <= order.tradeMoney){
                                   noDollar = true;
                              }
                         }if(student && student.length > 0){
                              balance = student[0]?.dollar;
                              role = "student";
                              if( balance < order.tradeMoney){
                                   noDollar = true;
                              }
                         }
                         res.render("pay",{
                              role,
                              orderNo:orderNo,
                              fromId:order.fromId,
                              toId:order.toId,
                              balance,
                              price:order.tradeMoney,
                              return_url,
                              notify_url,
                              noDollar,
                              pay_hander_url:config.protocal + "://" + config.hostname + ":" + config.port + "/api/pay/pay_handler"
                         });
                    }
               }
          }else{
               res.render("payError",{
                    isOk:true,
                    msg:"订单不存在"
               })
          }
      }catch(error){
               console.log(error);
               await updateOrderStatus(orderNo,1);
               logger.warn(req.ip + " - " + req.method + " - " + req.originalUrl + " - 支付失败")
               return res.send(new ResponseMessage(500,"网络错误",{orderNo}));
      }


}

exports.handlerPay = async (req,res) => {
     // 开启事务
     const session = await mongoose.startSession();
     session.startTransaction();
     try{
          const  { orderNo, fromId , toId , notify_url , role} = req.query;
          const order = (await findOrderByOrderNo(orderNo))[0];
          if(order){
               if(order.tradePayStatus === 2){
                    res.send({"code":500,message:"订单已过期","isOk":"true"})
              }else{
                   let sucCount = 0;
                   if(role === "teacher"){
                         const modify = await updateTeacherMoney(session,fromId,-order.tradeMoney)
                         if(modify.modifiedCount !== 0){
                              sucCount++;
                         }
                   }else if(role === "student"){
                         const modify = await updateStudentMoney(session,fromId,-order.tradeMoney)
                         if(modify.modifiedCount !== 0){
                              sucCount++;
                         }
                   }else{
                      res.send(new ResponseMessage(400,"缺少role参数",{}))
                   }
                   const studentModify = await updateStudentMoney(session,toId,order.tradeMoney)
                   const teacherModify = await updateTeacherMoney(session,toId,order.tradeMoney)
                   if(studentModify.modifiedCount !== 0 || teacherModify.modifiedCount !== 0){
                         sucCount++;
                   }
                   if(sucCount === 2){
                         await updateOrderStatus(orderNo,2);
                         // 这里其实应该再去通知异步地址 但是我们是自己写的服务器 其实可以省略 并不是提供给其他人使用的
                         paySocket.notify("pay",2)
                         res.send(new ResponseMessage(200,"success",{orderNo}))
                   }else{
                         res.send(new ResponseMessage(500,"网络错误",{orderNo:req.query.orderNo}))
                   }
                   await session.commitTransaction();
                   session.endSession();
              }
          }else{
               res.send(new ResponseMessage(500,"订单不存在",{orderNo:req.query.orderNo}))
          }
     }catch(error){
          await session.abortTransaction();
          session.endSession();
          res.send(new ResponseMessage(500,"支付失败",{orderNo:req.query.orderNo}))
     }
} 

exports.return_handler = (req,res) => {
     const { code } = req.query;
     if(code !== "200"){
          res.render("payError",{
               isOk:true,
          })
     }else{
          res.render("paySuccess")
     }
}

exports.notify_handler = (req,res) => {
     console.log(req.query);
}